local crc_ta = {
    0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
     0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef
}

function Xor(num1,num2)
	local tmp1 = num1
	local tmp2 = num2
	local str = ""
	repeat
		local s1 = tmp1 % 2
		local s2 = tmp2 % 2
		if s1 == s2 then
			str = "0"..str
		else
			str = "1"..str
		end
		tmp1 = math.modf(tmp1/2)
		tmp2 = math.modf(tmp2/2)
	until(tmp1 == 0 and tmp2 == 0)
	return tonumber(str,2)
end

function And(num1,num2)
    local tmp1 = num1
    local tmp2 = num2
    local ret = 0
    local count = 0
    repeat
        local s1 = tmp1 % 2
        local s2 = tmp2 % 2
        if s1 == s2 and s1 == 1 then
            ret = ret + 2^count
        end
        tmp1 = math.modf(tmp1/2)
        tmp2 = math.modf(tmp2/2)
        count = count + 1
    until(tmp1 == 0 and tmp2 == 0)
    return ret
end

function Cal_crc_half(pin, len)
    local crc = 0
    local da
    local bCRCHigh
    local bCRCLow

    for i = 1, len do
        da = math.floor(crc / 2^12)
        crc = (crc * 2^4) % 2^16
        crc = Xor(crc, crc_ta[And(Xor(da, math.floor((pin[i] / 2^4) % 16)), 0xF) + 1])

        da = math.floor(crc / 2^12)
        crc = (crc * 2^4) % 2^16
        crc = Xor(crc, crc_ta[And(Xor(da, And(pin[i], 0x0F)), 0xF) + 1])
    end

    bCRCLow = crc % 2^8
    bCRCHigh = math.floor(crc / 2^8)

    if bCRCLow == 0x28 or bCRCLow == 0x0d or bCRCLow == 0x0a then
        bCRCLow = bCRCLow + 1
    end

    if bCRCHigh == 0x28 or bCRCHigh == 0x0d or bCRCHigh == 0x0a then
        bCRCHigh = bCRCHigh + 1
    end

    crc = (bCRCHigh * 2^8) + bCRCLow
    return crc
end

-- local tabl = {0x5E,0x44,0x30,0x33,0x31,0x2d,0x30,0x20,0x30,0x20,0x30,0x20,0x31,0x20,0x30,0x20,0x30,0x30,0x30,0x20,0x30,0x20,0x30,0x20,0x30,0x20,0x30,0x20,0x30,0x20,0x30,0x20,0x30}
-- print (Cal_crc_half(tabl,#tabl))